package icu.zhhll.redis;

import redis.clients.jedis.Jedis;

import java.util.Collections;
import java.util.List;

/**
 * redis FIFO缓存(栈或队列)
 *
 * @author zh
 * @date 2023/9/15 16:56
 */
public class RedisFIFOCache {

    // 设置key对应的缓存队列长度
//    private static final Map<String, Integer> keyCacheSize = new ConcurrentHashMap<>();

    private static final String SIZE_PREFIX = "size:";

    /**
     * 设置该key的队列长度，不设置则没有长度限制，每个key只可以设置一次
     *
     * @param key
     * @param maxSize
     * @return
     */
    public static void setKeyCacheSize(String key, int maxSize) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            long eval = (long) jedis.eval("if redis.call('exists', KEYS[1]) == 0 then  redis.call('set',KEYS[1],ARGV[1]) " +
                            "return 1 else return 2 end",
                    Collections.singletonList(SIZE_PREFIX + key), Collections.singletonList(String.valueOf(maxSize - 1)));
            System.out.println("eval:" + eval);
            if (eval == 2) {
                throw new RuntimeException("不可重复设置该key的队列长度");
            }
        }

//        if (keyCacheSize.containsKey(key)) {
//            throw new RuntimeException("不可重复设置该key的队列长度");
//        }
//        keyCacheSize.put(key, maxSize - 1);
    }


    /**
     * 放入队列
     *
     * @param key
     * @param value
     */
    public static void put(String key, String value) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {

            jedis.lpush(key, value);
            if (jedis.exists(SIZE_PREFIX + key)) {
                jedis.ltrim(key, 0, Long.parseLong(jedis.get(SIZE_PREFIX + key)));
            }
        }
    }

    /**
     * 设置key的过期时间
     *
     * @param key
     * @param expireTime
     */
    public static void expire(String key, long expireTime) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            jedis.expire(key, expireTime);
        }
    }

    /**
     * 取最新的一条数据
     *
     * @param key
     */
    public static String getNewestOne(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.lindex(key, 0);

        }
    }

    /**
     * 弹出最新一条数据(弹出后数据会删除)
     *
     * @param key
     */
    public static String popNewestOne(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.lpop(key);
        }
    }

    /**
     * 获取最老的一条数据
     *
     * @param key
     * @return
     */
    public static String getOldOne(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.lindex(key, -1);
        }
    }

    /**
     * 弹出最老的一条数据(弹出后数据会删除)
     *
     * @param key
     * @return
     */
    public static String popOldOne(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.rpop(key);
        }
    }

    /**
     * 取最新的多条数据
     *
     * @param key
     */
    public static List<String> getNewest(String key, int limit) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.lrange(key, 0, limit - 1);
        }
    }

    /**
     * 获取队列长度
     *
     * @param key
     * @return
     */
    public static long size(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            return jedis.llen(key);
        }
    }

    /**
     * 删除队列中某元素
     *
     * @param key
     * @param element
     */
    public static void remove(String key, String element) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
            jedis.lrem(key, 0, element);
        }
    }

    /**
     * 删除该key
     *
     * @param key
     */
    public static void removeKey(String key) {
        try (Jedis jedis = SingletonJedisHolder.getInstance().getPool().getResource()) {
//            jedis.del(key);
//            if (jedis.exists(SIZE_PREFIX + key)) {
//                jedis.del(SIZE_PREFIX + key);
//            }
            jedis.eval("if redis.call('exists',KEYS[1]) == 1 then redis.call('del',KEYS[1]);redis.call('del',KEYS[2]) return 2" +
                    " else redis.call('del',KEYS[2]) return 1 end", 2, SIZE_PREFIX + key, key);
        }
    }
}
